﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Light.Utility.CMB
{
    /// <summary>
    /// 招行一网通支付工具类
    /// </summary>
    public class OneNetPayHelper
    {
        /// <summary>
        /// 生成商户校验码
        /// </summary>
        /// <param name="key">商户密钥 //测试环境为空， 生产环境见《一网通支付商户服务指南.doc》（可空）</param>
        /// <param name="date">订单日期	</param>
        /// <param name="branchID">开户分行号</param>
        /// <param name="coNo">商户号</param>
        /// <param name="billNo">订单号</param>
        /// <param name="amount">订单金额</param>
        /// <param name="merchantParam">商户自定义参数（可空）</param>
        /// <param name="merchantUrl">商户接受通知的URL</param>
        /// <param name="payerID">付款方用户标识。用来唯一标识商户的一个用户。长度限制为40字节以内。（可空）</param>
        /// <param name="payeeID">收款方的用户标识。（可空）</param>
        /// <param name="clientIP">商户取得的客户端IP，如果有多个IP用逗号”,”分隔。长度限制为64字节。（可空）</param>
        /// <param name="goodsType">商品类型，长度限制为8字节。（可空）</param>
        /// <param name="reserved">保留字段，长度限制为1024字节。填写内容为xml</param>
        /// <returns></returns>
        public static string GetMerchantCode(
            string key,
            string date,
            string branchID,
            string coNo,
            string billNo,
            string amount,
            string merchantParam,
            string merchantUrl,
            string payerID,
            string payeeID,
            string clientIP,
            string goodsType,
            string reserved)
        {
            string encodingName = "GBK";

            //1、第一步：产生加密内容
            //1) 原始内容：
            Random rand = new Random(1000);

            //“随机字符串|收款人<$CmbSplitter$>付款人<$ClientIP$>浏览器IP地址</$ClientIP$><$GoodsType$>商品类型</$GoodsType$><$Reserved$>附加数据</$Reserved$>”
            string content1 = string.Format("{0}|{1}<$CmbSplitter$>{2}<$ClientIP$>{3}</$ClientIP$><$GoodsType$>{4}</$GoodsType$><$Reserved$>{5}</$Reserved$>"
                , rand.Next(), payerID, payeeID, clientIP, goodsType, reserved);

            //2) 将原始内容以GBK编码转换成二进制内容。
            byte[] content1Bytes = Encoding.GetEncoding(encodingName).GetBytes(content1);

            //RC4加密的Key：将商户秘钥，以ASCII编码转成二进制，再进行MD5运算的结果作为Key。
            string keyMd5 = Serializer.CreateMD5(key, Encoding.ASCII);

            //3) 将二进制内容进行RC4加密。
            byte[] encryptedBytes = Light.Utility.Security.RC4Cryptor.RC4.EncryptEx(content1Bytes, keyMd5);

            //4) 将加密后的密文进行Base64编码。
            string encryptedStr1 = Convert.ToBase64String(encryptedBytes);

            //5) 将Base64编码结果中的“加号”替换成“星号”
            encryptedStr1 = encryptedStr1.Replace("+", "*");

            //2、第二步：计算哈希值，哈希值计算规则：SHA1结果用16进制字符串表示，计算步骤如下：
            //1) 组装原始内容：“商户秘钥+第一步形成的加密内容+日期+分行号+商户号+订单号+金额+商户附加参数+商户URL”
            string content2 = key + encryptedStr1 + date + branchID + coNo + billNo + amount + merchantParam + merchantUrl;
            //2) SHA1：将原始内容进行SHA1
            byte[] hashBytes = SHA1.Create().ComputeHash(Encoding.GetEncoding(encodingName).GetBytes(content2));
            //3) 将SHA1内容用16进制表示
            string hexStr = StringHelper.StringToHexString(hashBytes);

            return "|" + encryptedStr1 + "|" + hexStr;
        }
    }
}
